// ==UserScript==
// @name         网页转二维码
// @version      0.6.2
// @description  支持生成二维码、扫描二维码和自定义网址生成 - 优化界面版
// @author       Cursor+DeepSeek
// @match        http://*/*
// @match        https://*/*
// @grant        GM_addStyle
// @grant        GM_registerMenuCommand
// @grant        GM_setClipboard
// @grant        GM_openInTab
// @require      https://cdn.jsdelivr.net/npm/qrcode@1.5.1/build/qrcode.min.js
// @require      https://unpkg.com/@zxing/library@latest
// @icon         https://gitee.com/selling-surprises/Greasyfork-Script-repository/raw/main/%E5%AE%9E%E7%94%A8%E8%84%9A%E6%9C%AC/%E7%BD%91%E9%A1%B5%E8%BD%AC%E4%BA%8C%E7%BB%B4%E7%A0%81/Web-QR.png
// @updateURL    https://gitee.com/selling-surprises/Greasyfork-Script-repository/raw/main/%E5%AE%9E%E7%94%A8%E8%84%9A%E6%9C%AC/%E7%BD%91%E9%A1%B5%E8%BD%AC%E4%BA%8C%E7%BB%B4%E7%A0%81/%E7%BD%91%E9%A1%B5%E8%BD%AC%E4%BA%8C%E7%BB%B4%E7%A0%81%E5%A2%9E%E5%BC%BA%E7%89%88.user.js
// ==/UserScript==

(function() {
    'use strict';

    // 添加优化后的样式
    GM_addStyle(`
        #qrcode-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,0.85);
            display: none;
            justify-content: center;
            align-items: center;
            z-index: 999999;
            backdrop-filter: blur(5px);
            overflow-y: auto;
            padding: 10px;
        }
        
        #qrcode-container {
            background: #ffffff;
            border-radius: 12px;
            box-shadow: 0 8px 25px rgba(0,0,0,0.25);
            width: 100%;
            max-width: 340px;
            padding: 18px;
            position: relative;
            animation: popIn 0.3s ease-out;
            overflow: hidden;
            border: 1px solid #eaeaea;
        }
        
        @keyframes popIn {
            0% { transform: scale(0.8); opacity: 0; }
            100% { transform: scale(1); opacity: 1; }
        }
        
        #qrcode-title {
            font-size: 18px;
            font-weight: bold;
            color: #2c3e50;
            margin: 0 0 15px;
            text-align: center;
            padding-bottom: 12px;
            border-bottom: 1px solid #f0f0f0;
            position: relative;
        }
        
        #qrcode-title::after {
            content: '';
            position: absolute;
            bottom: -1px;
            left: 50%;
            transform: translateX(-50%);
            width: 60px;
            height: 3px;
            background: linear-gradient(90deg, #3498db, #8e44ad);
            border-radius: 3px;
        }
        
        #qrcode-tab {
            display: flex;
            border-bottom: 1px solid #f0f0f0;
            margin-bottom: 15px;
            gap: 4px;
        }
        
        .qrcode-tab-item {
            flex: 1;
            text-align: center;
            padding: 8px 0;
            cursor: pointer;
            font-weight: 500;
            color: #7f8c8d;
            transition: all 0.2s;
            position: relative;
            font-size: 13px;
            border-radius: 6px;
            background: #f8f9fa;
        }
        
        .qrcode-tab-item.active {
            color: #3498db;
            font-weight: 600;
            background: linear-gradient(135deg, #3498db30, #8e44ad20);
        }
        
        .qrcode-tab-item.active:after {
            content: '';
            position: absolute;
            bottom: -1px;
            left: 10%;
            width: 80%;
            height: 3px;
            background: linear-gradient(90deg, #3498db, #8e44ad);
            border-radius: 3px;
        }
        
        #qrcode {
            display: flex;
            justify-content: center;
            align-items: center;
            flex-direction: column;
            min-height: 170px;
            padding: 8px 0;
        }
        
        #qrcode img {
            max-width: 140px;
            max-height: 140px;
            border: 1px solid #f0f0f0;
            padding: 8px;
            border-radius: 8px;
            margin-bottom: 8px;
            box-shadow: 0 3px 10px rgba(0,0,0,0.1);
            background: white;
        }
        
        #qrcode p {
            font-size: 12px;
            color: #5a6268;
            max-width: 100%;
            word-break: break-all;
            text-align: center;
            margin: 5px 0;
            padding: 8px;
            background: #f8f9fa;
            border-radius: 6px;
            font-family: monospace;
            border: 1px solid #e9ecef;
            max-height: 70px;
            overflow-y: auto;
        }
        
        #custom-url-container, 
        #scan-container {
            display: none;
            flex-direction: column;
        }
        
        #custom-url-tip {
            color: #7f8c8d;
            font-size: 12px;
            margin: 5px 0 8px;
            text-align: center;
        }
        
        #custom-url-input-container {
            display: flex;
            gap: 8px;
            margin-bottom: 10px;
        }
        
        #custom-url-input {
            flex: 1;
            padding: 8px 10px;
            border: 1px solid #e1e4e8;
            border-radius: 6px;
            font-size: 13px;
            transition: all 0.3s;
            background: #f8fafc;
        }
        
        #custom-url-input:focus {
            border-color: #3498db;
            outline: none;
            box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.15);
            background: white;
        }
        
        #clear-url-btn {
            padding: 8px 12px;
            font-size: 12px;
            white-space: nowrap;
            background: #f0f2f5;
            border: 1px solid #e1e4e8;
            border-radius: 6px;
            cursor: pointer;
            transition: all 0.2s;
        }
        
        #clear-url-btn:hover {
            background: #e9ecef;
        }
        
        #custom-url-btn, 
        .scan-btn {
            background: linear-gradient(135deg, #3498db, #8e44ad);
            color: white;
            border: none;
            padding: 10px;
            border-radius: 6px;
            font-size: 13px;
            cursor: pointer;
            transition: all 0.3s;
            font-weight: 500;
            margin: 6px 0;
            box-shadow: 0 3px 5px rgba(52, 152, 219, 0.15);
        }
        
        #custom-url-btn:hover, 
        .scan-btn:hover {
            background: linear-gradient(135deg, #2980b9, #7d3c98);
            transform: translateY(-2px);
            box-shadow: 0 5px 8px rgba(52, 152, 219, 0.2);
        }
        
        #scan-area {
            position: relative;
            margin-bottom: 12px;
            border-radius: 6px;
            overflow: hidden;
            height: 200px;
            background: #000;
        }
        
        #scan-video {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        
        #scan-canvas {
            display: none;
        }
        
        #scan-frame {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            width: 70%;
            height: 160px;
            border: 2px solid #3498db;
            border-radius: 6px;
            display: none;
            box-shadow: 0 0 0 1000px rgba(0, 0, 0, 0.6);
        }
        
        #scan-line {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 3px;
            background: #e74c3c;
            animation: scanLine 2s infinite linear;
            box-shadow: 0 0 8px rgba(231, 76, 60, 0.7);
        }
        
        @keyframes scanLine {
            0% { top: 0; }
            100% { top: 100%; }
        }
        
        #scan-status {
            text-align: center;
            padding: 8px;
            color: #3498db;
            font-weight: 500;
            font-size: 13px;
        }
        
        #scan-controls {
            display: flex;
            gap: 8px;
            margin-bottom: 12px;
        }
        
        #file-input {
            display: none;
        }
        
        #scan-result {
            display: none;
            background: #f9f9f9;
            padding: 14px;
            border-radius: 6px;
            margin-top: 12px;
            border: 1px solid #e9ecef;
        }
        
        #result-text {
            font-size: 13px;
            color: #2c3e50;
            word-break: break-all;
            background: white;
            padding: 10px;
            border-radius: 6px;
            border-left: 4px solid #3498db;
            font-family: monospace;
            line-height: 1.5;
            max-height: 90px;
            overflow-y: auto;
        }
        
        #scan-result-actions {
            display: flex;
            gap: 8px;
            margin-top: 12px;
        }
        
        #close-btn {
            width: 100%;
            background: linear-gradient(135deg, #f8f9fa, #e9ecef);
            color: #495057;
            border: none;
            padding: 10px;
            border-radius: 6px;
            font-size: 13px;
            cursor: pointer;
            transition: all 0.3s;
            margin-top: 14px;
            font-weight: 500;
            border: 1px solid #e9ecef;
            display: block !important; /* 确保始终显示 */
        }
        
        #close-btn:hover {
            background: linear-gradient(135deg, #e9ecef, #dee2e6);
            transform: translateY(-2px);
            box-shadow: 0 3px 5px rgba(0,0,0,0.05);
        }
        
        .scan-btn {
            flex: 1;
        }
        
        .action-btn {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 6px;
            font-size: 12px;
        }
        
        .loading {
            color: #3498db;
            text-align: center;
            padding: 16px;
            font-weight: 500;
            font-size: 13px;
        }
        
        /* 统一二维码底部按钮样式 */
        .qrcode-footer {
            display: flex;
            justify-content: space-between;
            margin-top: 8px;
            gap: 8px;
            width: 100%;
        }
        
        .qrcode-footer-btn {
            flex: 1;
            min-height: 36px;
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 6px;
            font-size: 12px;
            font-weight: 500;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            transition: all 0.3s;
            padding: 8px 12px;
            box-sizing: border-box;
        }
        
        .download-btn {
            background: linear-gradient(135deg, #2ecc71, #27ae60);
            color: white;
            box-shadow: 0 3px 5px rgba(46, 204, 113, 0.15);
        }
        
        .download-btn:hover {
            background: linear-gradient(135deg, #27ae60, #219653);
            transform: translateY(-2px);
            box-shadow: 0 5px 8px rgba(46, 204, 113, 0.2);
        }
        
        .copy-btn {
            background: linear-gradient(135deg, #f8f9fa, #e9ecef);
            color: #333;
            border: 1px solid #e9ecef;
            box-shadow: 0 3px 5px rgba(0,0,0,0.05);
        }
        
        .copy-btn:hover {
            background: linear-gradient(135deg, #e9ecef, #dee2e6);
            transform: translateY(-2px);
            box-shadow: 0 5px 8px rgba(0,0,0,0.1);
        }
        
        .custom-tip {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100%;
            color: #95a5a6;
            font-size: 13px;
            text-align: center;
            padding: 15px;
        }
        
        .error-msg {
            color: #e74c3c;
            padding: 10px;
            text-align: center;
            font-weight: 500;
            background: rgba(231, 76, 60, 0.1);
            border-radius: 6px;
            margin: 5px 0;
        }
        
        /* 移动端优化 */
        @media (max-width: 768px) {
            #qrcode-overlay {
                padding: 8px;
                align-items: flex-start;
            }
            
            #qrcode-container {
                width: 95%;
                max-width: 95%;
                padding: 15px;
                margin-top: 8vh;
                max-height: 85vh;
                overflow-y: auto;
            }
            
            #qrcode-title {
                font-size: 17px;
                padding-bottom: 10px;
            }
            
            .qrcode-tab-item {
                font-size: 12px;
                padding: 8px 0;
            }
            
            #qrcode {
                min-height: 150px;
            }
            
            #qrcode img {
                max-width: 130px;
                max-height: 130px;
            }
            
            #scan-area {
                height: 180px;
            }
            
            #scan-controls {
                flex-direction: column;
            }
            
            .scan-btn {
                width: 100%;
            }
            
            #custom-url-input {
                padding: 9px;
                font-size: 13px;
            }
            
            #custom-url-btn, .scan-btn {
                padding: 10px;
                font-size: 13px;
            }
            
            #close-btn {
                padding: 10px;
                font-size: 13px;
                margin-top: 12px; /* 移动端调整间距 */
            }
            
            #result-text {
                font-size: 13px;
                padding: 9px;
            }
            
            /* 移动端按钮调整 */
            .qrcode-footer-btn {
                min-height: 40px;
                font-size: 13px;
                padding: 10px 12px;
            }
        }
        
        /* 小屏幕设备优化 */
        @media (max-width: 480px) {
            #qrcode-container {
                padding: 12px;
            }
            
            #qrcode-title {
                font-size: 16px;
            }
            
            .qrcode-tab-item {
                font-size: 11px;
                padding: 7px 0;
            }
            
            #qrcode img {
                max-width: 110px;
                max-height: 110px;
            }
            
            #scan-area {
                height: 160px;
            }
            
            .qrcode-footer-btn {
                min-height: 38px;
                font-size: 12px;
                padding: 9px 10px;
            }
        }
        
        /* 键盘焦点样式 */
        #custom-url-input:focus-visible,
        .qrcode-tab-item:focus-visible,
        #custom-url-btn:focus-visible,
        .scan-btn:focus-visible,
        #close-btn:focus-visible,
        .qrcode-footer-btn:focus-visible {
            outline: 2px solid #3498db;
            outline-offset: 2px;
        }
    `);

    // 创建背景遮罩和容器的函数
    function createQRCodeElements() {
        // 防止重复创建
        if (document.getElementById('qrcode-overlay')) {
            return document.getElementById('qrcode-overlay');
        }
        
        // 创建背景遮罩
        const overlay = document.createElement('div');
        overlay.id = 'qrcode-overlay';
        
        // 创建二维码容器
        const container = document.createElement('div');
        container.id = 'qrcode-container';
        
        const title = document.createElement('p');
        title.id = 'qrcode-title';
        title.textContent = '二维码工具';
        container.appendChild(title);
        
        // 创建tab切换
        const tabContainer = document.createElement('div');
        tabContainer.id = 'qrcode-tab';
        
        const tabs = [
            { text: '当前网页', tab: 'current' },
            { text: '自定义网址', tab: 'custom' },
            { text: '扫描二维码', tab: 'scan' }
        ];
        
        tabs.forEach(tabInfo => {
            const tab = document.createElement('div');
            tab.className = 'qrcode-tab-item';
            if (tabInfo.tab === 'current') tab.classList.add('active');
            tab.textContent = tabInfo.text;
            tab.dataset.tab = tabInfo.tab;
            tab.tabIndex = 0; // 添加tabindex使元素可聚焦
            tab.setAttribute('role', 'tab');
            tabContainer.appendChild(tab);
        });
        
        container.appendChild(tabContainer);
        
        const qrcodeElement = document.createElement('div');
        qrcodeElement.id = 'qrcode';
        container.appendChild(qrcodeElement);
        
        // 创建自定义URL输入区域
        const customUrlContainer = document.createElement('div');
        customUrlContainer.id = 'custom-url-container';
        customUrlContainer.style.display = 'none';
        
        const customUrlTip = document.createElement('p');
        customUrlTip.id = 'custom-url-tip';
        customUrlTip.textContent = '在下方输入网址并点击生成';
        customUrlContainer.appendChild(customUrlTip);
        
        // 输入框组 - 使用新的容器布局
        const inputContainer = document.createElement('div');
        inputContainer.id = 'custom-url-input-container';
        
        const customUrlInput = document.createElement('input');
        customUrlInput.id = 'custom-url-input';
        customUrlInput.type = 'text';
        customUrlInput.placeholder = '请输入网址，如 https://www.example.com';
        customUrlInput.value = 'https://';
        customUrlInput.autocomplete = 'off';
        
        const clearBtn = document.createElement('button');
        clearBtn.id = 'clear-url-btn';
        clearBtn.innerHTML = '清空';
        clearBtn.title = '清空输入框';
        clearBtn.addEventListener('click', () => {
            customUrlInput.value = '';
            customUrlInput.focus();
        });
        
        inputContainer.appendChild(customUrlInput);
        inputContainer.appendChild(clearBtn);
        customUrlContainer.appendChild(inputContainer);
        
        const customUrlBtn = document.createElement('button');
        customUrlBtn.id = 'custom-url-btn';
        customUrlBtn.innerHTML = '生成二维码';
        customUrlBtn.className = 'action-btn';
        
        customUrlContainer.appendChild(customUrlBtn);
        container.appendChild(customUrlContainer);
        
        // 创建扫码容器
        const scanContainer = document.createElement('div');
        scanContainer.id = 'scan-container';
        scanContainer.style.display = 'none';
        
        // 检测是否为移动设备
        const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
        
        // 扫描区域
        const scanArea = document.createElement('div');
        scanArea.id = 'scan-area';
        scanArea.style.display = 'none';
        
        const scanVideo = document.createElement('video');
        scanVideo.id = 'scan-video';
        scanVideo.setAttribute('playsinline', '');
        
        const scanCanvas = document.createElement('canvas');
        scanCanvas.id = 'scan-canvas';
        
        const scanFrame = document.createElement('div');
        scanFrame.id = 'scan-frame';
        
        const scanLine = document.createElement('div');
        scanLine.id = 'scan-line';
        scanFrame.appendChild(scanLine);
        
        // 添加扫描状态提示
        const scanStatus = document.createElement('div');
        scanStatus.id = 'scan-status';
        scanStatus.style.display = 'none';
        scanStatus.textContent = '正在启动相机...';
        
        scanArea.appendChild(scanVideo);
        scanArea.appendChild(scanCanvas);
        scanArea.appendChild(scanFrame);
        scanArea.appendChild(scanStatus);
        
        // 扫描控制按钮
        const scanControls = document.createElement('div');
        scanControls.id = 'scan-controls';
        
        const fileInput = document.createElement('input');
        fileInput.type = 'file';
        fileInput.id = 'file-input';
        fileInput.accept = 'image/*';
        
        const uploadBtn = document.createElement('button');
        uploadBtn.className = 'scan-btn action-btn';
        uploadBtn.innerHTML = '上传图片';
        uploadBtn.onclick = () => fileInput.click();
        
        const cameraBtn = document.createElement('button');
        cameraBtn.className = 'scan-btn action-btn';
        cameraBtn.id = 'camera-btn';
        cameraBtn.innerHTML = '开启相机';
        cameraBtn.style.display = isMobile ? 'block' : 'none';
        
        scanControls.appendChild(fileInput);
        scanControls.appendChild(uploadBtn);
        scanControls.appendChild(cameraBtn);
        
        // 扫描结果区域
        const scanResult = document.createElement('div');
        scanResult.id = 'scan-result';
        
        const resultText = document.createElement('p');
        resultText.id = 'result-text';
        
        const resultActions = document.createElement('div');
        resultActions.id = 'scan-result-actions';
        
        const visitBtn = document.createElement('button');
        visitBtn.className = 'scan-btn action-btn';
        visitBtn.innerHTML = '访问链接';
        
        const copyBtn = document.createElement('button');
        copyBtn.className = 'scan-btn action-btn';
        copyBtn.style.background = '#f8f9fa';
        copyBtn.style.color = '#333';
        copyBtn.innerHTML = '复制内容';
        
        const backBtn = document.createElement('button');
        backBtn.className = 'scan-btn action-btn';
        backBtn.style.background = '#f8f9fa';
        backBtn.style.color = '#333';
        backBtn.innerHTML = '返回扫描';
        backBtn.style.display = isMobile ? 'block' : 'none';
        
        resultActions.appendChild(visitBtn);
        resultActions.appendChild(copyBtn);
        resultActions.appendChild(backBtn);
        
        scanResult.appendChild(resultText);
        scanResult.appendChild(resultActions);
        
        scanContainer.appendChild(scanArea);
        scanContainer.appendChild(scanControls);
        scanContainer.appendChild(scanResult);
        
        container.appendChild(scanContainer);
        
        // 点击底部关闭按钮隐藏二维码 - 确保在所有平台都显示
        const closeButton = document.createElement('button');
        closeButton.id = 'close-btn';
        closeButton.innerHTML = '关闭';
        closeButton.title = '关闭二维码';
        container.appendChild(closeButton);
        
        overlay.appendChild(container);
        document.body.appendChild(overlay);
        
        // 添加关闭按钮的点击事件
        closeButton.addEventListener('click', function(e) {
            e.stopPropagation();
            overlay.style.display = 'none';
            stopCamera(); // 确保关闭相机
        });
        
        // 添加阻止事件冒泡
        overlay.addEventListener('click', function(e) {
            e.stopPropagation();
        });
        
        // 添加TAB切换事件
        const tabItems = container.querySelectorAll('.qrcode-tab-item');
        tabItems.forEach(item => {
            item.addEventListener('click', function(e) {
                e.stopPropagation();
                tabItems.forEach(tab => tab.classList.remove('active'));
                this.classList.add('active');
                
                const tabType = this.dataset.tab;
                customUrlContainer.style.display = 'none';
                scanContainer.style.display = 'none';
                qrcodeElement.style.display = 'none';
                
                if (tabType === 'current') {
                    generateQRCode(window.location.href);
                    qrcodeElement.style.display = 'flex';
                } else if (tabType === 'custom') {
                    customUrlContainer.style.display = 'flex';
                    qrcodeElement.style.display = 'flex';
                    qrcodeElement.innerHTML = '<div class="custom-tip">请输入网址并点击"生成二维码"</div>';
                    customUrlInput.focus(); // 自动聚焦输入框
                } else if (tabType === 'scan') {
                    scanContainer.style.display = 'block';
                    scanResult.style.display = 'none';
                }
            });
            
            // 添加键盘支持
            item.addEventListener('keydown', function(e) {
                if (e.key === 'Enter' || e.key === ' ') {
                    this.click();
                }
            });
        });
        
        // 添加自定义URL生成按钮事件
        customUrlBtn.addEventListener('click', function(e) {
            e.stopPropagation();
            
            const url = customUrlInput.value.trim();
            if (url && url !== 'https://' && isValidUrl(url)) {
                generateQRCode(url);
            } else {
                qrcodeElement.innerHTML = '<div class="error-msg">请输入有效网址</div>';
            }
        });
        
        // URL验证函数
        function isValidUrl(url) {
            try {
                new URL(url);
                return true;
            } catch (e) {
                return false;
            }
        }
        
        // 阻止输入框的点击事件冒泡到背景
        customUrlInput.addEventListener('click', function(e) {
            e.stopPropagation();
        });
        
        // 按回车也可以生成
        customUrlInput.addEventListener('keypress', function(e) {
            if (e.key === 'Enter') {
                customUrlBtn.click();
            }
        });

        // 添加扫码相关功能
        let stream = null;
        let scanning = false;
        let scanTimer = null;
        let lastScanResult = '';
        
        // 处理文件上传
        fileInput.addEventListener('change', function(e) {
            const file = e.target.files[0];
            if (file) {
                // 重置扫描结果显示
                const scanResult = document.getElementById('scan-result');
                scanResult.style.display = 'none';
                
                // 显示扫描状态
                const scanStatus = document.getElementById('scan-status');
                scanStatus.style.display = 'block';
                scanStatus.textContent = '正在处理图片...';
                
                const reader = new FileReader();
                reader.onload = function(e) {
                    const img = new Image();
                    img.onload = function() {
                        const canvas = document.getElementById('scan-canvas');
                        canvas.width = img.width;
                        canvas.height = img.height;
                        const ctx = canvas.getContext('2d');
                        ctx.drawImage(img, 0, 0);
                        
                        // 使用ZXing解码
                        try {
                            const hints = new Map();
                            const formats = [
                                ZXing.BarcodeFormat.QR_CODE,
                                ZXing.BarcodeFormat.CODE_128,
                                ZXing.BarcodeFormat.CODE_39,
                                ZXing.BarcodeFormat.DATA_MATRIX,
                                ZXing.BarcodeFormat.PDF_417
                            ];
                            hints.set(ZXing.DecodeHintType.POSSIBLE_FORMATS, formats);
                            hints.set(ZXing.DecodeHintType.TRY_HARDER, true);
                            
                            const reader = new ZXing.MultiFormatReader();
                            reader.setHints(hints);
                            
                            const luminanceSource = new ZXing.HTMLCanvasElementLuminanceSource(canvas);
                            const binaryBitmap = new ZXing.BinaryBitmap(new ZXing.HybridBinarizer(luminanceSource));
                            
                            const result = reader.decode(binaryBitmap);
                            if (result) {
                                handleScanResult(result.text, true, result.getBarcodeFormat().toString());
                            } else {
                                scanStatus.textContent = '未检测到二维码';
                                setTimeout(() => {
                                    scanStatus.style.display = 'none';
                                    fileInput.value = '';
                                }, 2000);
                            }
                        } catch (error) {
                            console.error('解码失败:', error);
                            scanStatus.textContent = '识别失败: ' + error.message;
                            setTimeout(() => {
                                scanStatus.style.display = 'none';
                                fileInput.value = '';
                            }, 2000);
                        }
                    };
                    img.src = e.target.result;
                };
                reader.readAsDataURL(file);
            }
        });

        // 处理相机扫描
        cameraBtn.addEventListener('click', async function() {
            try {
                if (stream) {
                    stopCamera();
                    cameraBtn.innerHTML = '开启相机';
                    scanning = false;
                    return;
                }
                
                // 先隐藏扫描区域，等待相机加载完成
                const scanArea = document.getElementById('scan-area');
                scanArea.style.display = 'none';
                
                const scanStatus = document.getElementById('scan-status');
                scanStatus.style.display = 'block';
                scanStatus.textContent = '正在启动相机...';
                
                // 更新按钮状态
                cameraBtn.disabled = true;
                cameraBtn.innerHTML = '启动中...';
                
                stream = await navigator.mediaDevices.getUserMedia({ 
                    video: { facingMode: "environment" }
                });
                scanVideo.srcObject = stream;
                
                // 使用更快速的方式检查视频就绪状态
                await new Promise((resolve) => {
                    if (scanVideo.readyState >= 3) {
                        resolve();
                    } else {
                        scanVideo.onloadeddata = resolve;
                    }
                });
                
                await scanVideo.play();
                cameraBtn.disabled = false;
                cameraBtn.innerHTML = '关闭相机';
                scanning = true;
                
                // 相机加载完成后再显示扫码区域和扫描框
                scanArea.style.display = 'block';
                scanFrame.style.display = 'block';
                scanLine.style.display = 'block';
                scanStatus.style.display = 'none';
                
                // 开始扫描循环
                scanLoop();
            } catch (err) {
                console.error('相机访问失败:', err);
                const scanStatus = document.getElementById('scan-status');
                scanStatus.style.display = 'block';
                scanStatus.textContent = '相机访问失败: ' + (err.message || '请确保已授予相机权限');
                
                cameraBtn.disabled = false;
                cameraBtn.innerHTML = '开启相机';
                
                setTimeout(() => {
                    scanStatus.style.display = 'none';
                }, 3000);
            }
        });

        // 扫描函数 - 优化性能
        function scanLoop() {
            if (!scanning || !stream) return;
            
            const canvas = document.getElementById('scan-canvas');
            const video = document.getElementById('scan-video');
            
            // 限制处理分辨率 (移动端优化)
            const maxWidth = 480;
            const scale = Math.min(1, maxWidth / video.videoWidth);
            canvas.width = video.videoWidth * scale;
            canvas.height = video.videoHeight * scale;
            
            const ctx = canvas.getContext('2d');
            ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
            
            try {
                // 创建ZXing解码器
                const hints = new Map();
                const formats = [
                    ZXing.BarcodeFormat.QR_CODE,
                    ZXing.BarcodeFormat.CODE_128,
                    ZXing.BarcodeFormat.CODE_39,
                    ZXing.BarcodeFormat.DATA_MATRIX,
                    ZXing.BarcodeFormat.PDF_417
                ];
                hints.set(ZXing.DecodeHintType.POSSIBLE_FORMATS, formats);
                hints.set(ZXing.DecodeHintType.TRY_HARDER, true);
                
                const reader = new ZXing.MultiFormatReader();
                reader.setHints(hints);
                
                // 创建ZXing图像对象
                const luminanceSource = new ZXing.HTMLCanvasElementLuminanceSource(canvas);
                const binaryBitmap = new ZXing.BinaryBitmap(new ZXing.HybridBinarizer(luminanceSource));
                
                // 尝试解码
                const result = reader.decode(binaryBitmap);
                
                if (result) {
                    const resultText = result.text;
                    // 防止重复扫描相同结果
                    if (resultText !== lastScanResult) {
                        lastScanResult = resultText;
                        // 扫描成功后立即处理结果
                        handleScanResult(resultText, false, result.getBarcodeFormat().toString());
                    }
                    return;
                }
            } catch (e) {
                // 解码失败，继续尝试
            }
            
            // 继续扫描
            scanTimer = requestAnimationFrame(scanLoop);
        }

        // 停止相机
        function stopCamera() {
            scanning = false;
            if (scanTimer) {
                cancelAnimationFrame(scanTimer);
                scanTimer = null;
            }
            
            if (stream) {
                stream.getTracks().forEach(track => {
                    track.stop();
                });
                stream = null;
            }
            
            const scanVideo = document.getElementById('scan-video');
            if (scanVideo) {
                scanVideo.srcObject = null;
            }
            
            // 确保扫描动画立即消失
            const scanFrame = document.getElementById('scan-frame');
            const scanLine = document.getElementById('scan-line');
            const scanArea = document.getElementById('scan-area');
            if (scanFrame) scanFrame.style.display = 'none';
            if (scanLine) scanLine.style.display = 'none';
            if (scanArea) scanArea.style.display = 'none';
            
            // 重置相机按钮状态
            const cameraBtn = document.getElementById('camera-btn');
            if (cameraBtn) {
                cameraBtn.disabled = false;
                cameraBtn.innerHTML = '开启相机';
            }
            
            // 隐藏状态提示
            const scanStatus = document.getElementById('scan-status');
            if (scanStatus) scanStatus.style.display = 'none';
        }

        // 处理扫描结果
        function handleScanResult(result, isImageUpload, format = 'UNKNOWN') {
            const resultText = document.getElementById('result-text');
            const scanResult = document.getElementById('scan-result');
            const scanArea = document.getElementById('scan-area');
            const scanControls = document.getElementById('scan-controls');
            const scanStatus = document.getElementById('scan-status');
            const scanFrame = document.getElementById('scan-frame');
            const scanLine = document.getElementById('scan-line');
            const cameraBtn = document.getElementById('camera-btn');
            
            // 关闭相机
            stopCamera();
            
            // 改进结果处理逻辑
            let finalResult = result;
            let resultType = '二维码';
            
            // 根据不同的码类型处理结果
            switch (format) {
                case 'QR_CODE':
                    resultType = '二维码';
                    try {
                        // 尝试多次解码
                        finalResult = decodeURIComponent(finalResult);
                        if (finalResult.includes('%')) {
                            try {
                                const decodedTwice = decodeURIComponent(finalResult);
                                if (decodedTwice !== finalResult) {
                                    finalResult = decodedTwice;
                                }
                            } catch (e) {}
                        }
                        // 过滤控制字符
                        finalResult = finalResult.trim().replace(/[\u0000-\u001F\u007F-\u009F]/g, '');
                    } catch (e) {}
                    break;
                case 'DATA_MATRIX':
                    resultType = 'Data Matrix码';
                    break;
                case 'PDF_417':
                    resultType = 'PDF 417码';
                    break;
            }
            
            // 隐藏扫码区域、扫描框和状态提示
            scanArea.style.display = 'none';
            scanFrame.style.display = 'none';
            scanLine.style.display = 'none';
            scanControls.style.display = 'flex';
            
            // 显示结果，包含码类型
            resultText.innerHTML = `<div style="margin-bottom: 8px;color: #666;font-weight:500;">识别类型: <span style="color:#3498db">${resultType}</span></div>${finalResult}`;
            scanResult.style.display = 'block';
            
            // 访问链接按钮
            const visitBtn = scanResult.querySelector('.scan-btn');
            visitBtn.onclick = () => {
                if ((format === 'QR_CODE' || format === 'DATA_MATRIX' || format === 'PDF_417') && 
                    (finalResult.startsWith('http://') || finalResult.startsWith('https://'))) {
                    if (typeof GM_openInTab === 'function') {
                        GM_openInTab(finalResult, { active: true });
                    } else {
                        window.open(finalResult, '_blank');
                    }
                } else {
                    alert('扫描结果：\n' + finalResult);
                }
            };
            
            // 复制按钮
            const copyBtn = scanResult.querySelectorAll('.scan-btn')[1];
            copyBtn.onclick = () => {
                if (typeof GM_setClipboard === 'function') {
                    GM_setClipboard(finalResult, 'text');
                    copyBtn.innerHTML = '已复制!';
                } else if (navigator.clipboard) {
                    navigator.clipboard.writeText(finalResult).then(() => {
                        copyBtn.innerHTML = '已复制!';
                    }).catch(() => {
                        alert('复制失败，请手动复制');
                    });
                } else {
                    // 兼容旧浏览器
                    const textarea = document.createElement('textarea');
                    textarea.value = finalResult;
                    document.body.appendChild(textarea);
                    textarea.select();
                    document.execCommand('copy');
                    document.body.removeChild(textarea);
                    copyBtn.innerHTML = '已复制!';
                }
                
                setTimeout(() => {
                    copyBtn.innerHTML = '复制内容';
                }, 2000);
            };
            
            // 返回按钮
            const backBtn = scanResult.querySelectorAll('.scan-btn')[2];
            if (isMobile) {
                backBtn.onclick = async () => {
                    try {
                        scanResult.style.display = 'none';
                        
                        // 先隐藏扫描区域，等待相机加载完成
                        scanArea.style.display = 'none';
                        
                        const scanStatus = document.getElementById('scan-status');
                        scanStatus.style.display = 'block';
                        scanStatus.textContent = '正在启动相机...';
                        
                        // 重新开启相机
                        stream = await navigator.mediaDevices.getUserMedia({ 
                            video: { facingMode: "environment" }
                        });
                        scanVideo.srcObject = stream;
                        
                        // 等待视频加载完成
                        await new Promise((resolve) => {
                            scanVideo.onloadeddata = resolve;
                        });
                        
                        await scanVideo.play();
                        cameraBtn.innerHTML = '关闭相机';
                        scanning = true;
                        
                        // 相机加载完成后再显示扫码区域和扫描框
                        scanArea.style.display = 'block';
                        scanFrame.style.display = 'block';
                        scanLine.style.display = 'block';
                        scanStatus.style.display = 'none';
                        
                        // 重新开始扫描
                        scanLoop();
                    } catch (err) {
                        console.error('相机访问失败:', err);
                        alert('无法访问相机');
                        scanControls.style.display = 'flex';
                    }
                };
            } else {
                backBtn.style.display = 'none';
            }
        }

        // 关闭时停止相机
        closeButton.addEventListener('click', stopCamera);
        document.addEventListener('keydown', function(e) {
            if (e.key === 'Escape') {
                stopCamera();
                const overlay = document.getElementById('qrcode-overlay');
                if (overlay) overlay.style.display = 'none';
            }
        });
        
        // 返回创建的overlay元素
        return overlay;
    }
    
    // 确保页面加载完毕后创建元素
    function ensureElementsCreated() {
        return createQRCodeElements();
    }
    
    // 生成二维码的通用函数
    function generateQRCode(url) {
        const qrcodeElement = document.getElementById('qrcode');
        if (!qrcodeElement) return;
        
        // 清空之前的二维码
        qrcodeElement.innerHTML = '<div class="loading">正在生成二维码...</div>';
        
        try {
            // 使用固定尺寸生成二维码
            QRCode.toDataURL(url, {
                width: 160,
                margin: 2,
                color: {
                    dark: '#000000',
                    light: '#ffffff'
                }
            }, function(error, dataURL) {
                if (error) {
                    console.error('生成二维码出错:', error);
                    qrcodeElement.innerHTML = '<div class="error-msg">生成失败: ' + error.message + '</div>';
                } else {
                    // 创建图片元素并设置数据URL
                    const img = document.createElement('img');
                    img.src = dataURL;
                    img.alt = '网址二维码';
                    qrcodeElement.innerHTML = '';
                    qrcodeElement.appendChild(img);
                    
                    // 添加显示当前网址的文本
                    const urlText = document.createElement('p');
                    urlText.textContent = url;
                    qrcodeElement.appendChild(urlText);
                    
                    // 创建统一的按钮容器
                    const btnContainer = document.createElement('div');
                    btnContainer.className = 'qrcode-footer';
                    
                    // 添加下载按钮 - 使用统一样式类
                    const downloadBtn = document.createElement('button');
                    downloadBtn.className = 'qrcode-footer-btn download-btn';
                    downloadBtn.innerHTML = '下载二维码';
                    downloadBtn.onclick = function() {
                        const link = document.createElement('a');
                        link.download = `qrcode-${new Date().getTime()}.png`;
                        link.href = dataURL;
                        link.click();
                    };
                    
                    // 添加复制链接按钮 - 使用统一样式类
                    const copyBtn = document.createElement('button');
                    copyBtn.className = 'qrcode-footer-btn copy-btn';
                    copyBtn.innerHTML = '复制链接';
                    copyBtn.onclick = function() {
                        if (typeof GM_setClipboard === 'function') {
                            GM_setClipboard(url, 'text');
                            copyBtn.innerHTML = '已复制!';
                        } else if (navigator.clipboard) {
                            navigator.clipboard.writeText(url).then(() => {
                                copyBtn.innerHTML = '已复制!';
                            }).catch(() => {
                                alert('复制失败，请手动复制');
                            });
                        } else {
                            // 兼容旧浏览器
                            const textarea = document.createElement('textarea');
                            textarea.value = url;
                            document.body.appendChild(textarea);
                            textarea.select();
                            document.execCommand('copy');
                            document.body.removeChild(textarea);
                            copyBtn.innerHTML = '已复制!';
                        }
                        
                        setTimeout(() => {
                            copyBtn.innerHTML = '复制链接';
                        }, 2000);
                    };
                    
                    btnContainer.appendChild(downloadBtn);
                    btnContainer.appendChild(copyBtn);
                    qrcodeElement.appendChild(btnContainer);
                }
            });
        } catch (e) {
            console.error('QRCode生成异常:', e);
            qrcodeElement.innerHTML = '<div class="error-msg">生成失败: ' + e.message + '</div>';
        }
    }

    // 显示二维码函数
    function showQRCode() {
        const overlay = ensureElementsCreated();
        if (!overlay) {
            console.error('无法创建二维码元素');
            return;
        }
        
        // 显示遮罩
        overlay.style.display = 'flex';
        
        // 默认显示当前网页的二维码
        const currentTab = document.querySelector('.qrcode-tab-item[data-tab="current"]');
        if (currentTab) {
            currentTab.click();
        } else {
            generateQRCode(window.location.href);
        }
    }

    // 注册暴力猴菜单命令
    try {
        GM_registerMenuCommand('显示二维码工具', showQRCode);
    } catch (e) {
        console.log('暴力猴菜单命令注册失败，请通过其他方式调用');
    }
    
    // 添加键盘快捷键 Ctrl+Q
    document.addEventListener('keydown', function(e) {
        if (e.ctrlKey && e.key === 'q') {
            e.preventDefault();
            showQRCode();
        }
    });
    
    // 确保页面加载完成后创建元素
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', ensureElementsCreated);
    } else {
        ensureElementsCreated();
    }
})();